#include "core/performance_monitor.h"
#include <fstream>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <algorithm>
#include <chrono>

namespace hft {

void PerformanceMonitor::monitorLoggerPerformance() {
    static auto last_check = std::chrono::system_clock::now();
    auto now = std::chrono::system_clock::now();
    
    if (std::chrono::duration_cast<std::chrono::seconds>(now - last_check).count() >= 60) {
        last_check = now;
        
        try {
            size_t system_queue = spdlog::get("system") ? spdlog::get("system")->queue_size() : 0;
            size_t trade_queue = spdlog::get("trade") ? spdlog::get("trade")->queue_size() : 0;
            size_t error_queue = spdlog::get("error") ? spdlog::get("error")->queue_size() : 0;
            
            spdlog::get("system")->info(
                "Logger performance - System: {} Trade: {} Error: {}",
                system_queue, trade_queue, error_queue);
        } catch (const std::exception& e) {
            spdlog::error("Failed to monitor logger performance: {}", e.what());
        }
    }
}

void PerformanceMonitor::recordMetric(MetricType type, const std::string& name, double value) {
    std::lock_guard<std::mutex> lock(mutex_);
    
    // 监控日志系统性能
    monitorLoggerPerformance();
    
    auto& data = metrics_[name];
    Metric metric{type, name, value, std::chrono::system_clock::now()};
    
    // 更新历史数据
    data.history.push_back(metric);
    if (data.history.size() > 10000) {  // 限制历史数据大小
        data.history.pop_front();
    }
    
    // 更新统计信息
    updateStats(data, value);
    
    // 记录日志
    spdlog::debug("Performance metric: {} = {:.2f}", name, value);
}

PerformanceStats PerformanceMonitor::getStats(MetricType type, const std::string& name) const {
    std::lock_guard<std::mutex> lock(mutex_);
    
    auto it = metrics_.find(name);
    if (it == metrics_.end()) {
        return PerformanceStats{0.0, 0.0, 0.0, 0.0, 0};
    }
    
    return calculateStats(it->second);
}

std::vector<Metric> PerformanceMonitor::getHistory(MetricType type, const std::string& name,
                                                 size_t max_points) const {
    std::lock_guard<std::mutex> lock(mutex_);
    
    auto it = metrics_.find(name);
    if (it == metrics_.end()) {
        return {};
    }
    
    const auto& history = it->second.history;
    size_t start_idx = history.size() > max_points ? history.size() - max_points : 0;
    
    return std::vector<Metric>(history.begin() + start_idx, history.end());
}

void PerformanceMonitor::reset() {
    std::lock_guard<std::mutex> lock(mutex_);
    metrics_.clear();
}

void PerformanceMonitor::exportReport(const std::string& filename) const {
    std::ofstream file(filename);
    if (!file) {
        spdlog::error("Failed to open report file: {}", filename);
        return;
    }
    
    file << "Performance Report\n";
    file << "=================\n\n";
    
    std::lock_guard<std::mutex> lock(mutex_);
    for (const auto& [name, data] : metrics_) {
        auto stats = calculateStats(data);
        
        file << "Metric: " << name << "\n";
        file << "  Count: " << stats.count << "\n";
        file << "  Min: " << std::fixed << std::setprecision(2) << stats.min_value << "\n";
        file << "  Max: " << stats.max_value << "\n";
        file << "  Average: " << stats.avg_value << "\n";
        file << "  Std Dev: " << stats.std_dev << "\n\n";
    }
}

void PerformanceMonitor::updateStats(MetricData& data, double value) {
    data.sum += value;
    data.sum_squared += value * value;
    data.count++;
    data.min_value = std::min(data.min_value.load(), value);
    data.max_value = std::max(data.max_value.load(), value);
}

PerformanceStats PerformanceMonitor::calculateStats(const MetricData& data) const {
    PerformanceStats stats;
    size_t count = data.count.load();
    
    if (count == 0) {
        return stats;
    }
    
    double sum = data.sum.load();
    double sum_squared = data.sum_squared.load();
    
    stats.count = count;
    stats.min_value = data.min_value.load();
    stats.max_value = data.max_value.load();
    stats.avg_value = sum / count;
    
    // 计算标准差
    if (count > 1) {
        double variance = (sum_squared - (sum * sum) / count) / (count - 1);
        stats.std_dev = std::sqrt(variance);
    } else {
        stats.std_dev = 0.0;
    }
    
    return stats;
}

} // namespace hft 